<!DOCTYPE html>
<script src="../../../resources/js-test.js"></script>
<script>

if (typeof testRunner !== 'undefined')
    testRunner.dumpAsText();

// ES6 polyfill
if (!String.prototype.contains) {
    String.prototype.contains = function(substring) {
        var startIndex = arguments[1] || 0;
        return this.indexOf(substring, startIndex) >= startIndex;
    };
}

function innerFunction() {
    document.appendChild(document);
}

function outerFunction() {
    innerFunction();
}

var e;

try {
    outerFunction();
} catch (ex) {
    e = ex;
}

shouldBeTrue('"stack" in e');
shouldBeEqualToString('typeof e.stack', 'string');
shouldBeTrue('e.stack.contains("innerFunction")');
shouldBeTrue('e.stack.contains("outerFunction")');

shouldBeEqualToString('Object.prototype.toString.call(e)', '[object DOMException]');
shouldBeEqualToString("e.toString()", "HierarchyRequestError: Failed to execute 'appendChild' on 'Node': Nodes of type '#document' may not be inserted inside nodes of type '#document'.");
shouldBeEqualToString('e.name', 'HierarchyRequestError');
shouldBeEqualToString("e.message", "Failed to execute 'appendChild' on 'Node': Nodes of type '#document' may not be inserted inside nodes of type '#document'.");
shouldBe('e.code', '3');

e.stack = 42;
// Don't use shouldBe because the FAIL case still happens on JSC and we don't want the output
// to depend on the path.
shouldBeTrue('e.stack === 42');

</script>
